package zelix.command;

import com.google.gson.*;
import org.lwjgl.opengl.Display;
import zelix.Core;
import zelix.gui.cloudconfig.CloudConfig;
import zelix.hack.Hack;
import zelix.managers.FileManager;
import zelix.managers.HackManager;
import zelix.utils.hooks.visual.ChatUtils;
import zelix.value.*;

import java.io.*;
import java.net.Socket;
import java.net.URL;
import java.util.Map;

public class Config extends Command {
	public static File configs;
	public static URL configurl;
	private static JsonParser jsonParser = new JsonParser();
	private static Gson gsonPretty = new GsonBuilder().setPrettyPrinting().create();

	public Config() {
		super("config");
	}

	@Override
	public void runCommand(String s, String[] args) {

		if (args[0].equals("reload")) {
			Core.fileManager = new FileManager();
		} else if (args[0].equals("save") && args[1] != null) {
			if (!FileManager.CONFIG.exists())
				FileManager.CONFIG.mkdir();
			configs = new File(FileManager.CONFIG, args[1] + ".json");
			saveHacks();
			ChatUtils.message("Successfully Save Config");
		} else if (args[0].equals("load") && args[1] != null) {
			configs = new File(FileManager.CONFIG, args[1] + ".json");
			if (configs.exists()) {
				loadHacks();
				ChatUtils.message("Successfully Load Config");
			} else {
				ChatUtils.message("NoFound Config");
			}
		}
		//Cloud Loser
		else if (args[0].equals("upload") && args[1] != null) {
			CloudConfig.UploadConfig(args[1]);
		}

	}

	@Override
	public String getDescription() {
		return "load cloud/local config";
	}

	@Override
	public String getSyntax() {
		return "config";
	}

	public static void saveHacks() {
		try {
			JsonObject json = new JsonObject();

			for (Hack module : HackManager.getHacks()) {
				JsonObject jsonHack = new JsonObject();
				jsonHack.addProperty("toggled", module.isToggled());
				jsonHack.addProperty("key", module.getKey());

				if (!module.getValues().isEmpty()) {
					for (Value value : module.getValues()) {
						if (value instanceof BooleanValue) {
							jsonHack.addProperty(value.getName(), (Boolean) value.getValue());
						}
						if (value instanceof NumberValue) {
							jsonHack.addProperty(value.getName(), (Number) value.getValue());
						}
						if (value instanceof ModeValue) {

							ModeValue modeValue = (ModeValue) value;
							for (Mode mode : modeValue.getModes()) {
								jsonHack.addProperty(mode.getName(), mode.isToggled());
							}
						}
					}
				}
				json.add(module.getName(), jsonHack);
			}

			PrintWriter saveJson = new PrintWriter(new FileWriter(configs));
			saveJson.println(gsonPretty.toJson(json));
			saveJson.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void loadHacks() {
		try {
			BufferedReader bufferedReader = new BufferedReader(new FileReader(configs));
			JsonObject jsonObject = (JsonObject) jsonParser.parse(bufferedReader);
			bufferedReader.close();

			for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
				Hack module = HackManager.getHack(entry.getKey());

				if (module == null)
					continue;

				JsonObject jsonObjectHack = (JsonObject) entry.getValue();

				module.setKey(jsonObjectHack.get("key").getAsInt());
				module.setToggled(jsonObjectHack.get("toggled").getAsBoolean());

				if (module.getValues().isEmpty())
					continue;

				for (Value value : module.getValues()) {
					if(jsonObjectHack.get(value.getName())==null) {
						if (value instanceof BooleanValue) {
							jsonObjectHack.addProperty(value.getName(), (Boolean) value.getValue());
						}
						if (value instanceof NumberValue) {
							jsonObjectHack.addProperty(value.getName(), (Number) value.getValue());
						}
						if (value instanceof ModeValue) {
							jsonObjectHack.addProperty(value.getName(), (Boolean) value.getValue());
						}
						saveHacks();
					}

					if (value instanceof BooleanValue)
						value.setValue(jsonObjectHack.get(value.getName()).getAsBoolean());
					if (value instanceof NumberValue)
						value.setValue(jsonObjectHack.get(value.getName()).getAsDouble());
					if (value instanceof ModeValue) {
						ModeValue modeValue = (ModeValue) value;
						for (Mode mode : modeValue.getModes())
							mode.setToggled(jsonObjectHack.get(mode.getName()).getAsBoolean());
					}
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static void loadCloudHacks() {
		try {

			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(configurl.openStream()));
			JsonObject jsonObject = (JsonObject) jsonParser.parse(bufferedReader);
			bufferedReader.close();

			for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
				Hack module = HackManager.getHack(entry.getKey());

				if (module == null)
					continue;

				JsonObject jsonObjectHack = (JsonObject) entry.getValue();

				module.setKey(jsonObjectHack.get("key").getAsInt());
				module.setToggled(jsonObjectHack.get("toggled").getAsBoolean());

				if (module.getValues().isEmpty())
					continue;

				for (Value value : module.getValues()) {
					if(jsonObjectHack.get(value.getName())==null) {
						if (value instanceof BooleanValue) {
							jsonObjectHack.addProperty(value.getName(), (Boolean) value.getValue());
						}
						if (value instanceof NumberValue) {
							jsonObjectHack.addProperty(value.getName(), (Number) value.getValue());
						}
						if (value instanceof ModeValue) {
							jsonObjectHack.addProperty(value.getName(), (Boolean) value.getValue());
						}
						saveHacks();
					}

					if (value instanceof BooleanValue)
						value.setValue(jsonObjectHack.get(value.getName()).getAsBoolean());
					if (value instanceof NumberValue)
						value.setValue(jsonObjectHack.get(value.getName()).getAsDouble());
					if (value instanceof ModeValue) {
						ModeValue modeValue = (ModeValue) value;
						for (Mode mode : modeValue.getModes())
							mode.setToggled(jsonObjectHack.get(mode.getName()).getAsBoolean());
					}
				}

			}
			ChatUtils.message("Successfully Load Cloud Config");
			//Core.notificationManager.add(new Notification("Successfully Load Cloud Config", Notification.Type.Success));
		} catch (Exception e) {
			ChatUtils.error("Failed To Load Cloud Config");
			//Core.notificationManager.add(new Notification("Failed To Load Cloud Config", Notification.Type.Success));
			e.printStackTrace();
		}

	}

	public static void saveCloudHacks() {
		try {
			JsonObject json = new JsonObject();

			for (Hack module : HackManager.getHacks()) {
				JsonObject jsonHack = new JsonObject();
				jsonHack.addProperty("toggled", module.isToggled());
				jsonHack.addProperty("key", module.getKey());

				if (!module.getValues().isEmpty()) {
					for (Value value : module.getValues()) {
						if (value instanceof BooleanValue) {
							jsonHack.addProperty(value.getName(), (Boolean) value.getValue());
						}
						if (value instanceof NumberValue) {
							jsonHack.addProperty(value.getName(), (Number) value.getValue());
						}
						if (value instanceof ModeValue) {

							ModeValue modeValue = (ModeValue) value;
							for (Mode mode : modeValue.getModes()) {
								jsonHack.addProperty(mode.getName(), mode.isToggled());
							}
						}
					}
				}
				json.add(module.getName(), jsonHack);
			}


			String ConfigMain = json.toString();
			//115.126.43.76
			//////////System.out.println("[Target][SaveConfig][String][" + ConfigMain + "]");
			Send("localhost", 19731,"[Target][SaveConfig][String]["+ConfigMain+"]");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String Send(String IP, int Port, String Message) {

		try {
			Socket socket = new Socket(IP, Port);
			OutputStream ops = socket.getOutputStream();
			OutputStreamWriter opsw = new OutputStreamWriter(ops);
			BufferedWriter bw = new BufferedWriter(opsw);
			bw.write(Message);
			bw.flush();
			InputStream ips = socket.getInputStream();
			InputStreamReader ipsr = new InputStreamReader(ips);
			BufferedReader br = new BufferedReader(ipsr);

			String s = null;

			while ((s = br.readLine()) != null) {
				return s;
			}

			socket.close();
		} catch (Exception e) {
			Display.setTitle("Failed Connect to The Server(0x66FF)");
			e.printStackTrace();
		}
		return null;
	}

}
